/*************************************************************************
 *
 *  Copyright (C) 2013 Florian Dang <florian.coin@gmail.com>
 *
 *  This file is part of NatusVerse.
 *
 *  NatusVerse is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  NatusVerse is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NatusVerse.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/

#ifndef INC_RAYTRACER_RAYTRACE_H_
#define INC_RAYTRACER_RAYTRACE_H_

/*!
 * \file        raytrace.h
 * \brief       raytracing engine
 * \author      Florian Dang
 * \date        2013
 */

#include <vector>

#include "graphics/graphics.h"
#include "raytracer/scene.h"
#include "raytracer/objects/camera.h"

//! Namespace for raytracer
/*!
  Anything related with the raytracer except image file processing,
  graphical output....
*/
namespace raytracer
{
class Raytrace
{
	public:
		typedef graphics::Graphics Window;
		typedef color::t_color     t_color;

		Raytrace() {}
		explicit Raytrace(Window win0) : win_(win0)
		{
			vec_color_.resize(win().GetW() * win().GetH());
		}

		Raytrace(Window win0, Scene scene0) : win_(win0), scene_(scene0)
		{
			vec_color_.resize(win().GetW() * win().GetH());
			set_view_dir();
			set_xinc();
			set_yinc();
			set_eye();
		}

		~Raytrace() {}

		inline Window win() const { return win_; }
		inline Scene scene() const { return scene_; }

		inline void set_scene(Scene scene0)
		{
			scene_ = scene0;
			set_view_dir();
			set_xinc();
			set_yinc();
			set_eye();
			scene_.set_num_objects();
			set_numlights();
		}

		inline int w() const { return win().GetW(); }
		inline int h() const { return win().GetH(); }

		inline Vector view_dir() const { return view_dir_; }
		inline Vector xinc() const { return xinc_; }
		inline Vector yinc() const { return yinc_; }
		inline Point  eye() const { return eye_; }
		inline int    numlights() const { return numlights_; }

		inline void set_view_dir() { view_dir_ = scene_.camera().ViewDir(); }
		inline void set_xinc() { xinc_ = scene_.camera().Xinc(); }
		inline void set_yinc() { yinc_ = scene_.camera().Yinc(); }
		inline void set_eye() { eye_ = scene_.camera().eye(); }
		inline void set_numlights() { numlights_ = static_cast<int>(scene_.vec_light().size()); }

		void  Raytracing();
		void  RaytraceScene(Scene scene);
		color::Color ComputePixel(int x, int y);

	private:
		Window win_;
		Scene  scene_;
		std::vector<t_color> vec_color_;

		Vector view_dir_;
		Vector xinc_;
		Vector yinc_;
		Point  eye_;
		int    numlights_;
};
}

#endif  // INC_RAYTRACER_RAYTRACE_H_
